

//import Datos.*;
//import Excepciones.*;
import Excepciones.ExcepcionExisteNombreDiccionario;
import java.util.*;

/**
 *
 * @author ricardo ramos
 */
public class ControladorDiccionario
{
    private ArrayList<String> nombreDiccionarios;
    private ArrayList<String> pathDiccionarios;
    private ArrayList<Trie> diccionarios;

    private GestorDatosDiccionario gestorDatos;

    /**
     * Constructor del controlador de diccionario
     */
    public ControladorDiccionario()
    {
        this.nombreDiccionarios = new ArrayList<String>();
        this.pathDiccionarios = new ArrayList<String>();
        this.diccionarios = new ArrayList<Trie>();
        this.gestorDatos = new GestorDatosDiccionario();
    }

    /**
     * Añade un nuevo diccionario con su nombre y path a la lista de nombreDiccionarios
     * @param nombre nombre del diccionario
     * @param path ruta donde se encuentra el diccionario
     * @throws ExcepcionExisteNombreDiccionario
     */
    public void NuevoDiccionario(String nombre, String path) throws ExcepcionExisteNombreDiccionario
    {
        if(!this.ExisteNombreDiccionario(nombre))
        {
            this.nombreDiccionarios.add(nombre);
            this.pathDiccionarios.add(path);
            this.diccionarios.add(new Trie(new Nodo()));
        }
        else throw new ExcepcionExisteNombreDiccionario("Ya existe un diccionario con el nombre "+nombre);
    }

    public Trie getTrie(String a) {
        int i;
        Trie t;
        for(i = 0; i < nombreDiccionarios.size(); ++i) {
            if(nombreDiccionarios.get(i).equals(a)) {
                t = diccionarios.get(i);
                return t;
            }
        }
        t = diccionarios.get(0);
        return t;
    }

    /**
     * Lista los nombres de los nombreDiccionarios disponibles en el controlador
     * @return lista de nombreDiccionarios
     * @throws ExcepcionVacio
     */
    public ArrayList<String> ListaDiccionarios() throws ExcepcionVacio
    {
        ArrayList<String> lista = new ArrayList<String>();

        if(this.nombreDiccionarios.isEmpty()) throw new ExcepcionVacio("Lista de nombreDiccionarios vacia");

        for(int i=0;i<this.nombreDiccionarios.size();i++) lista.add(nombreDiccionarios.get(i));

        return lista;
    }

    /**
     * Comprueba si el diccionario con el nombre entrado esta en la lista de nombreDiccionarios
     * @param nombre nombre del diccionario a buscar
     * @return booleano para comprobar la existencia
     */
    public boolean ExisteNombreDiccionario(String nombre)
    {
        boolean existe = false;

        for(int i=0;i<this.nombreDiccionarios.size();i++)
             if(nombreDiccionarios.get(i).equals(nombre)) existe = true;

        return existe;
    }

    /**
     * Borra de la lista de nombreDiccionarios el diccionario con el nombre pasado por parametro
     * @param nombre nombre del diccionario
     * @throws ExcepcionNoExisteNombreDiccionario
     */
    public void BorrarDiccionario(String nombre)// throws ExcepcionNoExisteNombreDiccionario
    {
        if(this.ExisteNombreDiccionario(nombre))
        {
            int pos = this.posicionDiccionario(nombre);
            this.nombreDiccionarios.remove(pos);
            this.pathDiccionarios.remove(pos);
            this.diccionarios.remove(pos);
        }
        //else throw new ExcepcionNoExisteNombreDiccionario("No existe el diccionario con el nombre "+nombre);
    }

    /**
     * Añade una palabra al diccionario
     * @param pal palabra a añadir al diccionario
     * @param nombre nombre del diccionario
     * @return booleano para indicar si se ha insertado o no la palabra
     * @throws ExcepcionNoExisteNombreDiccionario
     */
    public boolean AddPalabra(String pal, String nombre)// throws ExcepcionNoExisteNombreDiccionario
    {
       // if(!this.ExisteNombreDiccionario(nombre)) throw new ExcepcionNoExisteNombreDiccionario("No existe el diccionario con el nombre "+nombre);

        int pos = this.posicionDiccionario(nombre);

        if(pos>=0) return this.diccionarios.get(pos).insertarPalabra(pal);

        return false;
    }

    /**
     * Borra la palabra pasada por parámetro del diccionario seleccionado
     * @param pal palabra para borrar del diccionario
     * @param nombre nombre del diccionario
     * @return booleano para saber si se ha borrado la palabra o no
     * @throws ExcepcionNoExisteNombreDiccionario
     */
    public boolean BorrarPalabra(String pal, String nombre) //throws ExcepcionNoExisteNombreDiccionario
    {
        //if(!this.ExisteNombreDiccionario(nombre)) throw new ExcepcionNoExisteNombreDiccionario("No existe el diccionario con el nombre "+nombre);

        int pos = this.posicionDiccionario(nombre);

        if(pos>=0) return this.diccionarios.get(pos).eliminarPalabra(pal);

        return false;
    }

    /**
     * Modifica el path del diccionario seleccionado
     * @param nombre nombre del diccionario
     * @param nuevoPath string que contiene el nuevo path del diccionario
     * @throws ExcepcionNoExisteNombreDiccionario
     */
    public void ModificarPath(String nombre, String nuevoPath) //throws ExcepcionNoExisteNombreDiccionario
    {
        //if(!this.ExisteNombreDiccionario(nombre)) throw new ExcepcionNoExisteNombreDiccionario("No existe el diccionario con el nombre "+nombre);

        int pos = this.posicionDiccionario(nombre);

        if(pos>=0) this.pathDiccionarios.set(pos, nuevoPath);
    }

    /**
     * Modifica el nombre del diccionario entrado por parÃ¡metro
     * @param nombre nombre del diccionario
     * @param nuevoNombre string que contiene el nuevo nombre del diccionario
     * @throws ExcepcionNoExisteNombreDiccionario
     */
    public void ModificarNombre(String nombre, String nuevoNombre) //throws ExcepcionNoExisteNombreDiccionario
    {
         //if(!this.ExisteNombreDiccionario(nombre)) throw new ExcepcionNoExisteNombreDiccionario("No existe el diccionario con el nombre "+nombre);

         int pos = this.posicionDiccionario(nombre);

         if(pos>=0) this.nombreDiccionarios.set(pos, nuevoNombre);
    }

    /**
     * Retorna el path del diccionario pasado por parámetro
     * @param nombre nombre del diccionario
     * @return path ruta del fichero
     * @throws ExcepcionNoExisteNombreDiccionario
     */
    public String GetPathDeDiccionario(String nombre) //throws ExcepcionNoExisteNombreDiccionario
    {
        // if(!this.ExisteNombreDiccionario(nombre)) throw new ExcepcionNoExisteNombreDiccionario("No existe el diccionario con el nombre "+nombre);

         int pos = this.posicionDiccionario(nombre);

         if(pos>=0) return this.pathDiccionarios.get(pos);
         else return null;
    }

    /**
     * Comprueba si la palabra existe en el diccionario
     * @param nombre nombre del diccionario
     * @param palabra palabra a buscar en el diccionario
     * @return booleano para comprobar existencia
     * @throws ExcepcionNoExisteNombreDiccionario
     */
    public boolean ExisteEnDiccionario(String nombre, String palabra) //throws ExcepcionNoExisteNombreDiccionario
    {
        //if(!this.ExisteNombreDiccionario(nombre)) throw new ExcepcionNoExisteNombreDiccionario("No existe el diccionario con el nombre "+nombre);

        int pos = this.posicionDiccionario(nombre);

        try
        {
            if(pos>=0) return this.diccionarios.get(pos).Existe(palabra);
            else return false;
        }
        catch(Exception exc){ return false; }
    }

    /**
     * Devuelve el diccionario entrado en una lista de strings
     * @param nombre nombre del diccionario
     * @return diccionario en strings
     * @throws ExcepcionNoExisteNombreDiccionario
     */
    public ArrayList<String> DiccionarioEnString(String nombre)// throws ExcepcionNoExisteNombreDiccionario
    {
        //if(!this.ExisteNombreDiccionario(nombre)) throw new ExcepcionNoExisteNombreDiccionario("No existe el diccionario con el nombre "+nombre);

        int pos = this.posicionDiccionario(nombre);
        if(pos<0) return null;

        ArrayList<String> palabrasTrie = new ArrayList<String>();

        try
        {
            while(!this.diccionarios.get(pos).TrieVacio())
            {
                String pal = this.diccionarios.get(pos).PrimeraPalabra();
                this.diccionarios.get(pos).eliminarPalabra(pal);
                palabrasTrie.add(pal);
            }
        }
        catch(Exception ex){}

        for(int i=0;i<palabrasTrie.size();i++)
            this.diccionarios.get(pos).insertarPalabra(palabrasTrie.get(i));

        return palabrasTrie;
    }

    /**
     * Realiza una busqueda del patron en el diccionario seleccionado,
     * en caso de no obtener ningún resultado devuelve una lista vacia.
     * @param nombre nombre del diccionario
     * @param bus patron a buscar en el diccionario
     * @return lista de palabras con el resultado de la búsqueda
     * @throws ExcepcionNoExisteNombreDiccionario
     */
    public ArrayList<String> BusquedaEnDiccionario(String nombre, String bus) throws ExcepcionVacio// throws ExcepcionNoExisteNombreDiccionario, ExcepcionVacio
    {
       // if(!this.ExisteNombreDiccionario(nombre)) throw new ExcepcionNoExisteNombreDiccionario("No existe el diccionario con el nombre "+nombre);

        int pos = this.posicionDiccionario(nombre);

        if (pos>=0)
        {
            Trie triePal = this.diccionarios.get(pos).BuscarPalabras(bus);
            ArrayList<String> palabras = new ArrayList<String>();

            while(!triePal.TrieVacio())
            {
                String pal = triePal.PrimeraPalabra();
                triePal.eliminarPalabra(pal);
                palabras.add(pal);
            }

            return palabras;
        }

        return new ArrayList<String>();
    }

    /**
     * Retorna la posicion donde se encuentra dentro de la lista de nombreDiccionarios,
     * el diccionario seleccionado
     * @param nombre nombre del diccionario
     * @return entero indicando la posición en la lista de nombreDiccionarios
     */
    private int posicionDiccionario(String nombre)
    {
        for(int i=0;i<this.nombreDiccionarios.size();i++)
            if(nombreDiccionarios.get(i).equals(nombre)) return i;

        return -1;
    }

    /**
     * Carga del fichero asociado al diccionario seleccionado por parametro todas
     * las palabras de este, eliminando las ya existentes
     * @param nombre nombre del diccionario
     * @exception ExcepcionNoExisteNombreDiccionario
     */
    public void CargarDiccionario(String nombre) //throws ExcepcionNoExisteNombreDiccionario
    {
        //if(!this.ExisteNombreDiccionario(nombre)) throw new ExcepcionNoExisteNombreDiccionario("Ya existe un diccionario con el nombre "+nombre);

        try
        {
            int pos = this.posicionDiccionario(nombre);

            if(pos>=0)
            {
                String path = this.pathDiccionarios.get(pos);
                ArrayList<String> array = new ArrayList<String>();

                gestorDatos.AbrirComunicacion(path);

                do
                {
                    array = gestorDatos.CargaDiccionario(path);

                    for(int i=0;i<array.size();i++)
                    {
                        String pal = array.get(i);
                        this.diccionarios.get(pos).insertarPalabra(pal);
                    }
                }while(!array.isEmpty());

                gestorDatos.CerrarComunicacion();
            }
        }
        catch(Exception exc){}
    }

    /**
     * Guarda el diccionario en el fichero asociado al diccionario
     * @param nombre nombre del diccionario
     */
    public void GuardarDiccionario(String nombre) //throws ExcepcionNoExisteNombreDiccionario
    {
        //if(!this.ExisteNombreDiccionario(nombre)) throw new ExcepcionNoExisteNombreDiccionario("Ya existe un diccionario con el nombre "+nombre);

        int pos = this.posicionDiccionario(nombre);
        if(pos<0) return;

        try
        {
            ArrayList<String> palabrasTrie = this.DiccionarioEnString(nombre);
            String path = this.pathDiccionarios.get(pos);
            this.gestorDatos.GuardaDiccionario(palabrasTrie, path, false);
        }
        catch(Exception exc){}
    }

    /**
     * Devuelve si en la ruta pasada por parametro existe un fichero
     * @param path ruta del fichero
     * @return booleano devuelve si existe fichero o no
     */
    public boolean ExisteFichero(String path)
    {
        return this.gestorDatos.ExisteFichero(path);
    }

    /**
     * Retorna si en el path el fichero que hay es de lectura escritura
     * @param path ruta del fichero
     * @return booleano indica si es de lectura/escritura el fichero o no
     */
    public boolean EsFicheroRW(String path)
    {
        if(ExisteFichero(path)) return this.gestorDatos.PuedeRWFichero(path);
        else return false;
    }

    /**
     * Borra el fichero que se encuentra en el path pasado por parámetro
     * @param path path donde se encuentra el fichero
     * @return booleano para indicar si se ha borrado o no
     */
    public boolean BorrarFichero(String path)
    {
        if (this.gestorDatos.BorrarFichero(path)) return true;
        else return false;
    }

    /**
     * Modifica el tamaño de lineas a leer en cada acceso a un fichero
     * @param size tamaño de linea
     */
    public void SetSizeLectura(int size)
    {
        this.gestorDatos.SetSizeLectura(size);
    }

    /**
     * Devuelve el tamaño de lineas a leer en los accesos a fichero
     * @return entero con el tamaño de lectura de lineas
     */
    public int GetSizeLectura()
    {
        return this.gestorDatos.GetSizeLectura();
    }
     /**
     * Devuelve el indice de la palabra en el diccionario
     * @param pal String que representa la palabra a buscar
     * @param dic El nombre del diccionario
     * @return Entero con el indice de la palabra en el diccionario
     */
    public int GetIndicePalabra (String dic,String pal){
        int pos=this.posicionDiccionario(dic);
        if (pos>=0){
            ArrayList<String> v= this.DiccionarioEnString(dic);
            int i=0;
            while (i<v.size() && !pal.equals(v.get(i))){
                i++;
            }
            if (i==v.size())i=-1;
            return i;
        }
        return -1;
    }
     /**
     * Devuelve k palabras del diccionario desde i, si hay menos de k palabras devuelve las que haya
     * @param i El indice desde donde se obtendran.
     * @param k numero de palabras a obtener
     * @return Array con las palabras de i a k+i-1 o coincidentes
     */
    public String[] GetPalabras(String dic,int i, int k){
        int pos=this.posicionDiccionario(dic);
        if (pos>=0){
            ArrayList<String> v= this.DiccionarioEnString(dic);
            ArrayList<String> r = new ArrayList<String>();
            int ii=i;
            while (ii<v.size() && ii<(k+i)){
                r.add(v.get(ii));
                ii++;
            }
            return r.toArray(new String[0]);
        }
        return null;
    }
}

